<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    class Node {
      constructor (data) {
        this.prev = null
        this.next = null
        this.data = data
      }
    }
    class doubleLinkedList {
      constructor () {
        this.head = null
        this.tail = null
        this.length = 0
      }
      // 添加节点
      append (data) {
        // 判断data是否合法
        if (!data) return console.log(new Error('请输入合法的data'))
        // data合法
        const newNode = new Node(data)
        if (this.length === 0) {
          // 若没有元素存在则直接赋予头尾
          this.head = newNode
          this.tail = newNode
        } else {
          const { current, index } = this.getNodeByIndex(this.length - 1)
          current.next = newNode
          this.tail = newNode
          newNode.prev = current
        }
        this.length++
      }
      // 插入节点
      insert (position, data) {
        if (!(position || data)) return console.error(new Error('请确保输入两个参数 position, data'))
        if (!data) return console.error(new Error('请输入合法的data'))
        const newNode = new Node(data)
        if (this.length === 0 && position === 0) {
          this.head = newNode
          this.tail = newNode
        } else {
          if (position === 0) {
            const current = this.head
            this.head = newNode
            newNode.next = current
            current.prev = newNode
          } else if (position === this.length) { // position 为最后的节点
            const current = this.tail
            current.next = newNode
            newNode.prev = current
            this.tail = newNode
          } else {
            const { current } = this.getNodeByIndex(position)
            current.prev.next = newNode
            newNode.prev = current.prev
            newNode.next = current
            current.prev = newNode
          }
        }
        // 结束length + 1
        this.length++
      }
      // 查找某个节点
      indexOf (data) {
        if (!data) return console.error('请输入合法的data')
        let current = this.head
        let index = 0
        const result = []
        while (current) {
          if (current.data === data) {
            result.push(index)
          }
          index++
          current = current.next
        }
        return result.length === 0 ? undefined : result.length === 1 ? result[0] : result
      }
      // 删除某个节点
      removeAt (position) {
        if (!(0 <= position && position < this.length)) return console.log.error(new Error('请输入正确的position'))
        let current = this.head
        if (position === 0 && this.length === 1) {
          this.head = null
          this.tail = null
        } else {
          if (position === 0) {
            this.head = current.next
            current.next.prev = null
          } else if (position === this.length - 1) {
            current = this.tail
            current.prev.next = null
            this.tail = current.prev
          } else {
            let index = 0
            while (index < position) {
              index++
              current = current.next
            }
            current.prev.next = current.next
            current.next.prev = current.prev
          }
        }
        this.length--
        return current.data
      }
      // 根据data删除某个节点
      remove (data) {
        if (!data) return console.error(new Error('请输入合法的d数据ata'))
        const index = this.indexOf(data)
        return index ? this.removeAt(index) : undefined 
      }
      // 根据index查找node
      getNodeByIndex (position) {
        if  (!(0 <= position && position < this.length)) {
          console.error(new Error('请输入合法的index'))
        }
        let current = this.head
        let index = 0 
        while (index < position) {
          index++
          current = current.next
        }
        return {
          current: current,
          index
        }
      }
      // 获取第一个
      getFirst () {
        return this.head.data
      }
      // 获取最后一个
      getLast () {
        return this.tail.data
      }
      // 以正序按照字符串形式打印出来
      toString (headOrTail = 'head') {
        let current = this[headOrTail]
        let traversal = 'next'
        const result = ['head', '->']
        if (headOrTail === 'tail') {
          traversal = 'prev'
          result.splice(0, 2, 'tail', '->')
        }
        while (current) {
          result.push(current.data, '->')
          current = current[traversal]
        }
        result.push('end')
        return result.join(' ')
      }
    }
    const test = new doubleLinkedList()
    test.append(11)
    test.append(22)
    test.append(33)
    test.append(44)
    console.log(test.toString('head'))
    console.log(test.remove(44))
    console.log(test.toString('head'))
    console.log(test.toString('tail'))
    console.log(test.getFirst())
    console.log(test.getLast())
  </script>
</body>
</html>